﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SCRUM.Core.BusinessObjects;
using SCRUM.Core.DAO;

/// <summary>
/// This widget is primary created for Scrummaster. 
/// With this widget you can plan user stories you want to do during specific sprint.
/// </summary>
public partial class SprintPlanning : WidgetBase
{
	/// <summary>
	/// Gets or sets the total sprint estimation.
	/// </summary>
	/// <value>The total sprint estimation.</value>
	protected double TotalSprintEstimation { get; set; }

	protected double SprintTotal { get; set; }

	protected double SprintBusy { get; set; }

	protected double ManualTime { get; set; }

    /// <summary>
    /// Gets or sets the selected sprint ID.
    /// </summary>
    /// <value>The selected sprint ID.</value>
	public int? SelectedSprintID 
	{
		get 
        {
            return (int?)ViewState["SelectedSprintID"];
        }
        set
        {
            ViewState["SelectedSprintID"] = value;
        }
	}

	/// <summary>
	/// Gets the name of the widget. It must be exactly the same as the folder that contains the widget.
	/// </summary>
	/// <value></value>
	public override string Name
	{
		get { return "SprintPlanning"; }
	}

	/// <summary>
	/// Gets the title. Title is shown in the header of the widget container.
	/// </summary>
	/// <value>The title.</value>
	public override string Title
	{
		get { return (string)GetLocalResourceObject("Title"); }
	}

	/// <summary>
	/// Gets a value indicating whether this instance is editable.
	/// </summary>
	/// <value>
	/// 	<c>true</c> if this instance is editable; otherwise, <c>false</c>.
	/// </value>
	public override bool IsEditable
	{
		get { return false; }
	}

	/// <summary>
	/// This method works as a substitute for Page_Load. You should use this method for
	/// data binding etc. instead of Page_Load.
	/// </summary>
	public override void LoadWidget()
	{
		// Bind sprints to DropDownListSprints
		BindDropDownListSprints();

		// Load list of uncategorized user stories
		BindUnassignedUS();

        if (!IsPostBack)
        {
            SelectSprint(this, new EventArgs());
        }
	}

	private void LoadSprintTimeInfo()
	{
		int sprintID = -1;
		if (Int32.TryParse(DropDownListSprints.SelectedValue, out sprintID))
		{
			SprintTimeInfo timeInfo = DAOSprint.GetTimeInfo(sprintID);

			this.SprintTotal = timeInfo == null ? 0 : timeInfo.TotalHours;
            this.SprintBusy = timeInfo == null ? 0 : timeInfo.AvailibleHours;
		}
	}

    /// <summary>
    /// Binds the data into DropDownListSprints.
    /// </summary>
	protected void BindDropDownListSprints()
	{
        DropDownListSprints.Items.Add(new ListItem("...", String.Empty));
		DropDownListSprints.DataSource = SCRUM.Core.DAO.DAOSprint.GetAllFutureSprints();
		DropDownListSprints.DataTextField = "Name";
		DropDownListSprints.DataValueField = "ID";
		DropDownListSprints.DataBind();
	}

	/// <summary>
	/// Binds the uncategorized user stories.
	/// </summary>
	private void BindUnassignedUS()
	{
		int sprintID = this.SelectedSprintID.HasValue ? this.SelectedSprintID.Value : Int32.Parse(DropDownListSprints.SelectedValue);
        int projectID = DropDownListSprints.SelectedValue == String.Empty ? -1 : (DAOProject.GetProjectByReleaseID((DAORelease.GetReleaseBySprintID(sprintID)).ID)).ID;
		ListViewUnassignedUS.DataSource = SCRUM.Core.DAO.DAOUserStory.GetUnassignedStories(projectID);
		ListViewUnassignedUS.DataBind();
	}

	/// <summary>
	/// Shows the edit.
	/// </summary>
	public override void ShowEdit()
	{
		throw new NotImplementedException();
	}

	/// <summary>
	/// Hides the edit.
	/// </summary>
	public override void HideEdit()
	{
		throw new NotImplementedException();
	}

    /// <summary>
    /// Selects the sprint.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
	protected void SelectSprint(object sender, EventArgs e)
	{
		BindUserStoriesInSprint();
		BindUnassignedUS();
	}

	/// <summary>
	/// Binds user stories for selected sprint
	/// </summary>
	protected void BindUserStoriesInSprint()
	{
        if (String.IsNullOrEmpty(this.DropDownListSprints.SelectedValue))
        {
            ListViewUserStoriesInSprint.DataSource = new List<UserStory>();
            ListViewUserStoriesInSprint.DataBind();
            return;
        }
		LoadSprintTimeInfo();
		ListViewUserStoriesInSprint.DataSource = SCRUM.Core.DAO.DAOUserStory.GetAllUserStoriesForSprint(
			Int32.Parse(this.DropDownListSprints.SelectedValue));
		ListViewUserStoriesInSprint.DataBind();
        this.SelectedSprintID = Int32.Parse(this.DropDownListSprints.SelectedValue);
	}

    /// <summary>
    /// Occurs when command on listview happens.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Web.UI.WebControls.ListViewCommandEventArgs"/> instance containing the event data.</param>
    protected void ListViewItemCommand(object sender, ListViewCommandEventArgs e)
    {
        switch (e.CommandName)
        {
            case "AddToSprint":
                UserStory us = ((IList<UserStory>)this.ListViewUnassignedUS.DataSource)[(e.Item as ListViewDataItem).DataItemIndex];
                TextBox inputEstimation = (TextBox)e.Item.FindControl("InputEstimation");
                us.Estimation = Int32.Parse(inputEstimation.Text);
                us.Sprint = this.SelectedSprintID == null ? null : DAOSprint.GetSprintById((int)this.SelectedSprintID);
                SCRUM.Core.DAO.DAOUserStory.UpdateUserStory(us);
				SCRUM.Core.DAO.DAOUserStory.UpdateUserStorySprint(us.ID, this.SelectedSprintID);
                break;
            case "RemoveFromSprint":
                
                SCRUM.Core.DAO.DAOUserStory.UpdateUserStorySprint(Int32.Parse(e.CommandArgument.ToString()), null);
                break;
            case "UpdateEstimation":
                us = ((IList<UserStory>)this.ListViewUnassignedUS.DataSource)[(e.Item as ListViewDataItem).DataItemIndex];
                inputEstimation = (TextBox)e.Item.FindControl("InputEstimation");
                us.Estimation = Int32.Parse(inputEstimation.Text);
                SCRUM.Core.DAO.DAOUserStory.UpdateUserStory(us);
                break;
            default:
                break;
        }
        BindUnassignedUS();
        BindUserStoriesInSprint();
    }

	/// <summary>
	/// ListViewUserStoriesInSprint OnItemDataBound occured.
	/// </summary>
	/// <param name="sender">The sender.</param>
	/// <param name="e">The <see cref="System.Web.UI.WebControls.ListViewItemEventArgs"/> instance containing the event data.</param>
	protected void UserStoriesInSprintItemDataBound(object sender, ListViewItemEventArgs e)
	{
		if (e.Item.ItemType == ListViewItemType.DataItem)
		{
			UserStory userStory = ((ListViewDataItem)e.Item).DataItem as UserStory;
			this.TotalSprintEstimation += userStory.Estimation;
		}
	}

	/// <summary>
	/// ListViewUserStoriesInSprint OnDataBound occured.
	/// </summary>
	/// <param name="sender">The sender.</param>
	/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
	protected void UserStoriesInSprintDataBound(object sender, EventArgs e)
	{
		TextBox manualTime = (TextBox)ListViewUserStoriesInSprint.FindControl("TextBoxManualTime");
		if (manualTime != null)
		{
			try
			{
				Localize LocalizeManualTime = (Localize)ListViewUserStoriesInSprint.FindControl("LocalizeManualTime");

				double value = 0;
				if (Double.TryParse(manualTime.Text.Replace(".",","), out value))
				{
					this.ManualTime = value;
				}
				else
				{
					throw new SCRUM.Core.Exceptions.SCRUMFormatException(LocalizeManualTime.Text.Replace(":",""), manualTime.Text);
				}
			}
			catch (SCRUM.Core.Exceptions.SCRUMFormatException ex)
			{
				ShowRawOperationResult(MessageType.Error, ex.Message);
			}
			finally
			{

			}
		}

		Label literalTotal = (Label)ListViewUserStoriesInSprint.FindControl("LiteralTotal");
        if (literalTotal != null)
        {
            literalTotal.Text = this.TotalSprintEstimation.ToString();
			if ((this.SprintTotal - this.SprintBusy - this.ManualTime) < this.TotalSprintEstimation)
			{
				this.ShowOperationResult(MessageType.Warning, "sprint_sp_full");
				literalTotal.ForeColor = System.Drawing.Color.Red;
			}
			else
			{
				literalTotal.ForeColor = System.Drawing.Color.Black;
			}
        }

		Literal literalSprintTotal = (Literal)ListViewUserStoriesInSprint.FindControl("LiteralSprintTotal");
		if (literalSprintTotal != null)
		{
			literalSprintTotal.Text = this.SprintTotal.ToString();
		}
		Literal literalSprintBusy = (Literal)ListViewUserStoriesInSprint.FindControl("LiteralSprintBusy");
		if (literalSprintBusy != null)
		{
			literalSprintBusy.Text = this.SprintBusy.ToString();
		}
		Literal literalSprintAvailable = (Literal)ListViewUserStoriesInSprint.FindControl("LiteralSprintAvailable");
		if (literalSprintAvailable != null)
		{
			literalSprintAvailable.Text = (this.SprintTotal - this.SprintBusy - this.ManualTime - this.TotalSprintEstimation).ToString();
		}	
	}

	protected void ApplyManualTime(object sender, EventArgs e)
	{
		
	}

    /// <summary>
    /// Handles the PreRender event of the Page control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void Page_PreRender(object sender, EventArgs e)
    {
        if ((this.ListViewUnassignedUS.DataSource == null) || ((this.ListViewUnassignedUS.DataSource as IList<UserStory>).Count == 0))
        {
            this.ShowOperationResult(MessageType.Warning, "no_data_for", (string)GetLocalResourceObject("Unassigned"));
        }
        if ((this.ListViewUserStoriesInSprint.DataSource == null) || ((this.ListViewUserStoriesInSprint.DataSource as IList<UserStory>).Count == 0))
        {
            this.ShowOperationResult(MessageType.Warning, "no_data_for_filters");
        }
    }
}
